home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-01-11 | 10.2 KB | 349 lines | [TEXT/CWIE] |
- // DataPersistence.c
- // -------------------
- // v1.3
- // feedback: macdev@tnuctip.com
-
- #include "SWIncludes.h"
-
- #define OWNER
- #include "DataPersistence.h"
- #undef OWNER
-
-
-
- // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
- // THESE ROUTINES MAY BE CUSTOMIZED TO YOUR OWN DATA
- // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
-
- #pragma mark •————Customizable————
-
- ///--------------------------------------------------------------------------------------
- // This do-nearly-nothing routine is here to allow easy customizing for whatever error
- // management your app may need.
- ///--------------------------------------------------------------------------------------
-
- #include <stdio.h>
- #include <string.h>
-
- void SWGErrorReportingStub (OSErr err)
- {
- SInt16 i;
-
- if (err != noErr)
- {
- ///
- // this should be replaced with whatever alert or action is appropriate for each app
- ///
-
- for (i = 0; i < 3; i++)
- {
- SysBeep (1); // even such a basic signal may be useful to reveal a problem
- Delay (2, nil);
- }
- }
- }
-
-
-
- // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
- // PUBLIC : called by your app
- // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
-
- #pragma mark •—————Public—————
-
-
- ///--------------------------------------------------------------------------------------
- // Open file; if it does not exist, switch to internal resource mode
- // After this call, excepting system errors, a resource file is guaranteed to be ready.
- ///--------------------------------------------------------------------------------------
-
- OSErr SWGOpenPersistenceFile (void)
- {
- OSErr err = noErr; // default (if already open)
- SInt16 vRef = 0;
- SInt32 dirID = 0L;
- FSSpec fspec;
-
- if ((! gSWGPersistenceFileIsOpen) && (! gSWGPersistenceUsesAppFork))// if app's rez fork used, continue
- {
- err = FSMakeFSSpec (vRef, dirID, gPersistenceFileName, &fspec);
- if (err == fnfErr)
- {
- gSWGPersistenceUsesAppFork = true; // no separate file, will use app
- gSWGPersistenceFileIsOpen = true; // functionally true
- err = noErr;
- }
- else if (err == noErr)
- {
- gSWGPreviousResFile = CurResFile();
- gSWGPersistenceResFile = FSpOpenResFile (&fspec, fsCurPerm);
- err = ResError (); // should be == noErr mostly
- if (err == noErr)
- {
- UseResFile (gSWGPersistenceResFile);
- err = ResError (); // will be == noErr
- gSWGPersistenceFileIsOpen = true;
- }
- }
- }
-
- return err;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // Close the file and flush disk
- ///--------------------------------------------------------------------------------------
-
- void SWGClosePersistenceFile (void)
- {
- if (gSWGPersistenceFileIsOpen && (! gSWGPersistenceUsesAppFork))
- {
- CloseResFile (gSWGPersistenceResFile);
- gSWGPersistenceFileIsOpen = false;
-
- UseResFile (gSWGPreviousResFile);
-
- gSWGPreviousResFile = -1;
- gSWGPersistenceResFile = -1;
-
- (void) FlushVol ("\p", 0);
-
- // restore the standard resource type
- _SWGRestoreResourceType ();
- }
- }
-
-
- ///--------------------------------------------------------------------------------------
- // If file is not open, we open it now, and return true (or false in case of error).
- // If another routine has already opened the file, we do nothing and return false.
- //
- // This lets the caller routine know if it has actually opened the file:
- // - If it has, it's also responsible for closing the file before returning (using
- // SWGClosePersistenceFile).
- // - If it has not, the file was previously opened by another routine, and caller knows
- // it is _not_ responsible for closing it.
- //
- // This is useful for some special cases, illustrated in SpritePersistence.c.
- //
- // The newType argument optionally overrides DataPersistence's standard resource type.
- // If kNoNewType is passed, there will be no override.
- // Important note: when file is closed (SWGClosePersistenceFile), the type will be
- // automatically restored to it's default value, so don't worry about it.
- ///--------------------------------------------------------------------------------------
-
- Boolean SWGOpenPersistenceFileConditionally (OSType newType)
- {
- if (! gSWGPersistenceFileIsOpen)
- {
- OSErr err;
-
- err = SWGOpenPersistenceFile ();
- if (err != noErr)
- SWGErrorReportingStub (err);
- else // only if file opening succeeded
- {
- if (newType != kNoNewType)
- _SWGOverrideResourceType (newType);
- }
-
- return (err == noErr);
- }
- return false;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // Do the actual saving job for a record.
- // May return various system errors, including notOpenErr, or resource-related errors.
- ///--------------------------------------------------------------------------------------
-
- OSErr SWGSaveRecord (Ptr recordP, Size recSize, SInt16 resourceID)
- {
- OSErr err = noErr;
- Handle h;
- Boolean createdResource = false;
- Boolean readPhase = true;
-
- if (! gSWGPersistenceFileIsOpen)
- return notOpenErr;
-
- // Read the rez before writing; if not found, create it; if different size, adjust it
-
- while (readPhase)
- {
- h = GetResource (gSWGPersistenceResourceType, resourceID);
- if (h == nil)
- {
- err = ResError ();
- if ((err == noErr) // that's a strange one, but it does happen
- || (err == resNotFound)) // first time, must create it
- {
- err = noErr; // is not an error for us
- h = NewHandleClear (recSize);
- if (h == nil)
- return memFullErr;
-
- createdResource = true;
- }
- readPhase = false; // even if err
- }
- else if (recSize != GetHandleSize (h))
- {
- RemoveResource (h); // remove from file, will be recreated with new size
- // h is a now a regular handle
- SetHandleSize (h, recSize);
- err = MemError ();
- createdResource = true;
- readPhase = false;
- }
- else
- readPhase = false; // normal case
- }
-
- if (err == noErr)
- {
- err = PtrToXHand (recordP, h, recSize);
- if (err == noErr)
- {
- if (createdResource)
- AddResource (h, gSWGPersistenceResourceType, resourceID, "\p");
- else
- ChangedResource (h);
-
- err = ResError (); // normally == noErr
- if (err == noErr)
- {
- WriteResource (h);
- err = ResError ();
- }
- }
-
- SWGErrorReportingStub (err);
-
- ReleaseResource (h);
- }
- else // maybe handle allocated & not used ?
- {
- if (h != nil) // wasn't used for a resource
- DisposeHandle (h);
- }
-
- return err;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // This is provided for symmetry with SWGLoadString. Currently it's identical to SWGSaveRecord.
- ///--------------------------------------------------------------------------------------
-
- // currently implemented as a macro: #define SWGSaveString SWGSaveRecord
-
-
-
- ///--------------------------------------------------------------------------------------
- // Do the actual loading job for a record.
- // May return various system errors, including notOpenErr, or resource-related errors.
- // Special errors kDataSizeBiggerError/kDataSizeSmallerError: resource didn't have the expected size.
- // Will copy as many bytes as possible into recordP.
- // If resource not found, return the error code returned by system (resNotFound).
- ///--------------------------------------------------------------------------------------
-
- OSErr SWGLoadRecord (Ptr recordP, Size recSize, SInt16 resourceID)
- {
- OSErr err = noErr;
- Handle h;
-
- if (! gSWGPersistenceFileIsOpen)
- return notOpenErr;
-
- h = GetResource (gSWGPersistenceResourceType, resourceID);
- if (h == nil)
- {
- err = ResError ();
- if (err == noErr) // does happen
- err = resNotFound;
-
- // init the record (no need to optimize this, it's an error situation)
- while (recSize--)
- *recordP++ = 0;
- }
- else
- {
- Size hSize;
-
- hSize = GetHandleSize (h);
- if (recSize != hSize) // most times will be ==
- {
- if (recSize > hSize)
- {
- recSize = hSize; // don't access memory outside handle
- err = kDataSizeSmallerError;
- }
- else // will not copy all the handle data
- err = kDataSizeBiggerError;
- }
-
- BlockMove (*h, recordP, recSize); // that's a memory-safe call, no handle locking necessary
-
- ReleaseResource (h);
- }
-
- return err;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // Do the actual loading job for a string. The difference with SWGLoadString is that a
- // *smaller* size than expected is not considered an error.
- // May return various system errors, including notOpenErr, or resource-related errors.
- // Special error kDataSizeBiggerError: resource was *bigger* than the expected size.
- // Will copy as many bytes as possible into recordP.
- // If resource not found, return the error code returned by system (resNotFound).
- ///--------------------------------------------------------------------------------------
-
- OSErr SWGLoadString (Ptr stringP, Size maxStringSize, SInt16 resourceID)
- {
- OSErr err = noErr;
-
- err = SWGLoadRecord (stringP, maxStringSize, resourceID);
- if (err == kDataSizeSmallerError) // smaller data is normal for a string
- err = noErr;
-
- return err;
- }
-
-
-
- // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
- // PRIVATE : internal use only
- // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
-
- #pragma mark •—————Private—————
-
-
- ///--------------------------------------------------------------------------------------
- // Allows using other rez types than the standard one. SpritePersistence uses this so as
- // to avoid collisions between it's resource numbers and yours.
- ///--------------------------------------------------------------------------------------
-
- void _SWGOverrideResourceType (OSType newType)
- {
- gSWGPersistenceResourceType = newType;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // Restores the standard rez type.
- ///--------------------------------------------------------------------------------------
-
- void _SWGRestoreResourceType (void)
- {
- gSWGPersistenceResourceType = kDefaultPersistenceRezType;
- }
-
-
-
- // end
-